<template>
  <div class="container">
    <div class="bgImage">
      <div class="msgBox">
        <div class="msgPanel" ref="msgPanel">
          <div :class="['msgItem', item.self ? 'selfItem' : '']" v-for="(item, i) in msgList" :key="i">
            <span v-if="!item.self && item.userName">{{ item.userName }}:</span>
            {{ item.content }}
            <span v-if="item.self && item.userName">:{{ item.userName }}</span>
          </div>
        </div>
      </div>
      <div class="msgFooter">
        <!-- 聊天输入框 -->
        <input type="text" v-model="msgStr" class="msgInput" @keydown="keyDonFun" />
        <button class="msgBtn" @click="sendMsg" :disabled="!isInRoom">发送</button>
      </div>
    </div>

  </div>
</template>
<script>
// 发定时ping消息的时间间隔
const TIMESPACE = 5000;
export default {
  data () {
    return {
      // 输入框的字符串
      msgStr: '',
      userName: 'bla bal',
      userId: '',
      roomId: '',
      // websocket 实例
      ws: null,
      // 存聊天消息数组 {content:'内容',name:'名字',self:true}
      msgList: [],
      isInRoom: false,
      setIntervalId: -1,
      setTimeoutId: -1,
    }
  },
  mounted () {

    this.interRoom();
  },
  methods: {
    // 本地发消息事件 ping
    sendMsg () {
      const content = this.msgStr.trim();

      if (!content) return console.log('请输入消息内容！');
      if (!this.isInRoom) return //没有在房间内 不执行

      const msgData = {
        content: this.msgStr,// 显示聊天内容
        userName: this.userName,
        self: true
      };

      this.msgList.push(msgData);
      // 滚动到底部
      this.scrollToBottom();
      // document.querySelector('.msgPanel').

      const sendData = {
        userName: this.userName,
        userId: this.userId,
        roomId: this.roomId,
        event: '',
        content: this.msgStr,
      }
      // 发到服务端
      this.ws.send(JSON.stringify(sendData));

      this.msgStr = '';
    },
    scrollToBottom () {
      this.$nextTick(() => {
        // 聊天内容滚动到底部
        this.$refs.msgPanel.scrollIntoView(false);
      })
    },
    // 键盘事件
    keyDonFun (event) {
      if (event.keyCode === 13) {
        this.sendMsg();
      }
    },
    // 初始化
    wsConnet () {
      // 生成websoket 实例
      this.ws = new WebSocket('ws://localhost:9001');
    },
    interRoom () {
      // console.log('params',this.$route.query)
      const { query: { name, id , roomId} } = this.$route;
      this.userName = name;
      this.userId = id;
      this.roomId = roomId;

      this.wsConnet();


      this.setIntervalId = setInterval(() => {
        if (this.setTimeoutId !== -1) {
          clearTimeout(this.setTimeoutId);
          this.setTimeoutId = -1;
        }

        this.setTimeoutId = setTimeout(() => {
          // ws超时了
          // 清理定时器
          this.removeAllListener();
          // 重新 进入
          this.interRoom();
        }, 10000)

        // 给服务端发一个ping 消息
        this.ws.send(JSON.stringify({
          event: 'heartBeat',// 心跳检测命令
          content: 'ping',
        }))

      }, TIMESPACE)

      // ws连接成功 可以通信了
      this.ws.onopen = () => {
        const sendData = {
          userName: this.userName,
          userId: this.userId,
          roomId: this.roomId,
          event: 'login'
        }
        this.isInRoom = true;
        // 把进入的消息发送到ws服务端
        this.ws.send(JSON.stringify(sendData));
      }
      // ws断开连接
      this.ws.onclose = () => {
        const sendData = {
          userName: this.userName,
          userId: this.userId,
          roomId: this.roomId,
          event: 'logout'
        }
        // 把进入的消息发送到ws服务端
        this.ws.send(JSON.stringify(sendData));

        this.isInRoom = false;
      }
      // 监听服务端的消息 (自己发的消息ws服务端也返回)
      this.ws.onmessage = (evt) => {
        const msgData = JSON.parse(evt.data);
        const { event, userName, content, userId } = msgData || {};

        // console.log('onmessage event', msgData);
        if (content === 'pong' && event === 'heartBeat') {
          // console.log('pong')
          clearTimeout(this.setTimeoutId);
          this.setTimeoutId = -1;
          return;
        }

        if (event === 'login') {
          this.msgList.push({
            content: '欢迎' + userName + '加入!'
          });
        } else if (event === 'logout') {
          this.msgList.push({
            content: userName + ':离开聊天室！'
          });
        } else {
          // 判断是否是自己发的消息 如果是自己的消息return 不执行msgList.push
          if (userId === this.userId) return

          // 这是接收的聊天消息
          this.msgList.push({
            content,
            userName
          });
          // console.log('this.msgList', this.msgList, userName)
          this.scrollToBottom();
        }
        // console.log('this.msgList2', this.msgList);
      }
    },
    removeAllListener () {
      clearInterval(this.setIntervalId);
      clearTimeout(this.setTimeoutId);
      this.setTimeoutId = -1;
      this.setIntervalId = -1;
      this.msgList = [];
      this.isInRoom = false;
    },
    close(){
      // 关闭websocket
      this.ws?.close();
    },
    // 组件卸载前
    beforeDestroy() {
      // 关闭 socket
      this.close();
      // 清理事件
      this.removeAllListener();
    },
  }
}
</script>
<style>
.container {
  width: 360px;
  height: 240px;
  margin: 0 auto;
  font-size: 16px;
  position: relative;
}

.bgImage {
  background-color: transparent;
  background-repeat: no-repeat;
  background-size: cover;
  background-position: center;
  width: 100%;
  padding: 0;
  height: 100%;
  background-image: url("../../assets/images/bg_chatroom.jpeg");
  color: #fff;
  box-sizing: border-box;
  padding-bottom: 80px;
  display: flex;
  flex-direction: column;
}

.roomInfo {
  height: 80px;
  padding-top: 40px;
  display: flex;
  justify-content: flex-start;
  align-items: center;
}

.roomNickname {
  margin-right: 8px;
  font-weight: bold;
  font-size: 16px;
}

.onLineBox {
  min-width: 100px;
  padding: 0 20px;
  margin-left: 20px;
  box-sizing: border-box;
  height: 30px;
  border-radius: 10.66667vw;
  background: rgba(0, 0, 0, 0.2);
  box-sizing: border-box;
  font-size: 14px;
  line-height: 30px;
}

.nickname {
  color: #fff;
  font-weight: bold;
  text-align: center;
}

.msgBox {
  font-size: 14px;
  flex: 1;
  overflow-y: scroll;
}

.msgPanel {}

.msgItem {
  padding: 0 20px;
  margin-top: 8px;
  text-align: left;
}

.msgItem:first-child {
  margin-top: 0;
}

.msgItem.selfItem {
  text-align: right;
}

.msgFooter {
  position: absolute;
  bottom: 40px;
  left: 0;
  width: 100%;
  display: flex;
  align-items: center;
  padding: 0 24px;
  box-sizing: border-box;
  height: 30px;
}

.msgInput {
  width: 200px;
  outline: none;
  border: none;
  border-radius: 4px;
  padding: 6px 8px;
  background: rgba(0, 0, 0, 0.2);
  caret-color: #fff;
  color: #fff;
  font-size: 14px;
}

.msgInput::placeholder {
  color: #fff;
  font-size: 14px;
}

.msgBtn {
  width: 60px;
  margin-left: 16px;
  border-radius: 13px;
  padding: 0 12px;
  height: 26px;
  font-size: 14px;
  color: #fff;
  background: #208CFF;
  display: flex;
  justify-content: center;
  align-items: center;
  box-sizing: border-box;
  cursor: pointer;
}
</style>


